package com.facebook.app.client.presenter;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.facebook.app.client.ClusteringMethod;
import com.facebook.app.client.FacebookServiceAsync;
import com.facebook.app.client.event.ActionFailedEvent;
import com.facebook.app.client.view.ClusterStrategyChoiceView;
import com.facebook.app.shared.clustering.Clusterable;
import com.facebook.app.shared.facebookData.FacebookData;
import com.facebook.app.shared.facebookData.FacebookFriend;
import com.facebook.app.shared.facebookData.FacebookLike;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionModel;

public class ClusteringEndedPresenter implements Presenter {

	public interface Display {
		Panel getSelectedFriendsPanel();
		Label getSelectedFriendsLabel();
		CellList<FacebookData> getSelectedFriends();
		Panel getCommonLikesPanel();
		Image getLoadingImage();
		Label getCommonLikesLabel();
		CellList<FacebookData> getCommonLikes();
		TabPanel getTabPanel();
		Widget asWidget(List<Clusterable> clusteringResults, SelectionModel<Clusterable> selectionModelForClusterables, SelectionModel<ClusteringMethod> clusteringMethodSelectionModel);
	}

	private final FacebookServiceAsync rpcService;
	private final HandlerManager eventBus;
	private final Display view;
	private final String accessToken;

	private final List<Clusterable> clusteringResults;

	private final MultiSelectionModel<Clusterable> multiSelectionModel = new MultiSelectionModel<Clusterable>();

	public ClusteringEndedPresenter(FacebookServiceAsync rpcService,
			HandlerManager eventBus, Display view, String accessToken,
			List<Clusterable> clusteringResults) {
		this.rpcService = rpcService;
		this.eventBus = eventBus;
		this.view = view;
		this.accessToken = accessToken;
		this.clusteringResults = clusteringResults;

		bind();
	}

	@Override
	public void go(final HasWidgets container) {
		container.clear();
		container.add(view.asWidget(clusteringResults, multiSelectionModel,
				new ClusterStrategyChoicePresenter(eventBus,
						new ClusterStrategyChoiceView()).createSelectionModel()));
	}

	private void bind() {

		view.getTabPanel().addSelectionHandler(new SelectionHandler<Integer>() {
			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				if (event.getSelectedItem() == view.getTabPanel()
						.getWidgetIndex(view.getSelectedFriendsPanel())) {
					
					displaySelectedFriends();
				} else if (event.getSelectedItem() == view.getTabPanel()
						.getWidgetIndex(view.getCommonLikesPanel())) {
					
					fetchAndDisplayCommonLikesOfSelectedFriends();
				}
			}
		});
	}

	private void fetchAndDisplayCommonLikesOfSelectedFriends() {
		
		view.getCommonLikes().setVisible(false);
		view.getCommonLikesLabel().setVisible(false);
		view.getLoadingImage().setVisible(true);

		Set<Clusterable> selectedSet = multiSelectionModel
				.getSelectedSet();
		List<FacebookFriend> selectedFriends = new ArrayList<FacebookFriend>(
				selectedSet.size());

		for (Clusterable element : selectedSet) {
			if (element instanceof FacebookFriend) {
				selectedFriends.add((FacebookFriend) element);
			}
		}

		rpcService.importLikesForFriends(selectedFriends, accessToken,
				new AsyncCallback<Set<FacebookLike>>() {
					@Override
					public void onSuccess(Set<FacebookLike> commonLikes) {
						if (commonLikes != null && commonLikes.size() > 0) {
							List<FacebookData> commonLikeList = new ArrayList<FacebookData>(
									commonLikes);

							view.getCommonLikes().setRowData(commonLikeList);
							view.getLoadingImage().setVisible(false);
							view.getCommonLikes().setVisible(true);
							view.getCommonLikes().redraw();
						} else {
							view.getLoadingImage().setVisible(false);
							view.getCommonLikesLabel().setVisible(true);
						}
					}

					@Override
					public void onFailure(Throwable caught) {
						eventBus.fireEvent(new ActionFailedEvent(
								"Like import failed!"));
					}
				});
	}
	
	private void displaySelectedFriends() {
		
		view.getSelectedFriends().setVisible(false);
		view.getSelectedFriendsLabel().setVisible(false);

		Set<Clusterable> selectedSet = multiSelectionModel
				.getSelectedSet();

		List<FacebookData> selectedItems = new ArrayList<FacebookData>(
				selectedSet.size());
		
		for (Clusterable element : selectedSet) {
			if (element instanceof FacebookData) {
				selectedItems.add((FacebookData) element);
			}
		}

		if (selectedItems != null && selectedItems.size() > 0) {

			view.getSelectedFriends().setRowData(selectedItems);
			view.getSelectedFriends().setVisible(true);
			view.getSelectedFriends().redraw();
		} else {
			view.getSelectedFriendsLabel().setVisible(true);
		}
	}

}
